home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_001 / amigaterm / amigaterm.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  33KB  |  1,113 lines

  1. /************************************************************************
  2. *  a terminal program that has ascii and xmodem transfer capability
  3. *
  4. *  use esc to abort xmodem transfer
  5. *
  6. *  written by Michael Mounier
  7. ************************************************************************/
  8.  
  9. /*  compiler directives to fetch the necessary header files */
  10. #include <exec/types.h>
  11. #include <exec/exec.h>
  12. #include <intuition/intuition.h>
  13. #include <intuition/intuitionbase.h>
  14. #include <graphics/gfxbase.h>
  15. #include <graphics/gfx.h>
  16. #include <graphics/text.h>
  17. #include <graphics/regions.h>
  18. #include <graphics/copper.h>
  19. #include <graphics/gels.h>
  20. #include <devices/serial.h>
  21. #include <devices/keymap.h>
  22. #include <hardware/blit.h>
  23. #include <stdio.h>
  24. #include <ctype.h>
  25. #include <libraries/dos.h>
  26.  
  27. #define INTUITION_REV 1
  28. #define GRAPHICS_REV  1
  29.  
  30. /* things for xmodem send and recieve */
  31. #define SECSIZ   0x80
  32. #define TTIME    30          /* number of seconds for timeout */
  33. #define BufSize  0x1000     /* Text buffer */
  34. #define ERRORMAX 10        /* Max errors before abort */
  35. #define RETRYMAX 10       /* Maximum retrys before abort */
  36. #define SOH      1       /* Start of sector char */
  37. #define EOT      4      /* end of transmission char */
  38. #define ACK      6     /* acknowledge sector transmission */
  39. #define NAK      21   /* error in transmission detected */
  40.  
  41. static char
  42.     bufr[BufSize];
  43. static int
  44.     fd,
  45.     timeout = FALSE;
  46. static long
  47.     bytes_xferred;
  48.  
  49. /*   Intuition always wants to see these declarations */
  50. struct IntuitionBase *IntuitionBase;
  51. struct GfxBase *GfxBase;
  52.  
  53. /* my window structure */
  54. struct NewWindow NewWindow = {
  55.    0,
  56.    0,
  57.    639,
  58.    199,
  59.    0,
  60.    1,
  61.    CLOSEWINDOW | RAWKEY | MENUPICK | NEWSIZE,
  62.    WINDOWCLOSE | SMART_REFRESH | ACTIVATE | WINDOWDRAG
  63.    | WINDOWDEPTH | WINDOWSIZING | REPORTMOUSE,
  64.    NULL,
  65.    NULL,
  66.    "AMIGA Terminal",
  67.    NULL,
  68.    NULL,
  69.    100, 35,
  70.    640, 200,
  71.    WBENCHSCREEN,
  72. };
  73.  
  74. struct Window *mywindow;             /* ptr to applications window */
  75. struct IntuiMessage *NewMessage;    /* msg structure for GetMsg() */
  76.  
  77. static char toasc ();
  78. static unsigned char readchar ();
  79.  
  80. /*****************************************************
  81. *                     File Menu
  82. *****************************************************/
  83.  
  84. /* define maximum number of menu items */
  85. #define FILEMAX 4
  86.  
  87. /*   declare storage space for menu items and
  88.  *   their associated IntuiText structures
  89.  */
  90. struct MenuItem FileItem[FILEMAX];
  91. struct IntuiText FileText[FILEMAX];
  92.  
  93. /*****************************************************************/
  94. /*    The following function initializes the structure arrays    */
  95. /*   needed to provide the File menu topic.                      */
  96. /*****************************************************************/
  97. InitFileItems()
  98. {
  99. short n;
  100.  
  101. /* initialize each menu item and IntuiText with loop */
  102. for( n=0; n<FILEMAX; n++ )
  103.    {
  104.    FileItem[n].NextItem = &FileItem[n+1];
  105.    FileItem[n].LeftEdge = 0;
  106.    FileItem[n].TopEdge = 11 * n;
  107.    FileItem[n].Width = 135;
  108.    FileItem[n].Height = 11;
  109.    FileItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX;
  110.    FileItem[n].MutualExclude = 0;
  111.    FileItem[n].ItemFill = (APTR)&FileText[n];
  112.    FileItem[n].SelectFill = NULL;
  113.    FileItem[n].Command = 0;
  114.    FileItem[n].SubItem = NULL;
  115.    FileItem[n].NextSelect = 0;
  116.  
  117.    FileText[n].FrontPen = 0;
  118.    FileText[n].BackPen = 1;
  119.    FileText[n].DrawMode = JAM2;     /* render in fore and background */
  120.    FileText[n].LeftEdge = 0;
  121.    FileText[n].TopEdge = 1;
  122.    FileText[n].ITextFont = NULL;
  123.    FileText[n].NextText = NULL;
  124.    }
  125. FileItem[FILEMAX-1].NextItem = NULL;
  126.  
  127. /* initialize text for specific menu items */
  128. FileText[0].IText = (UBYTE *)"Ascii Capture";
  129. FileText[1].IText = (UBYTE *)"Ascii Send";
  130. FileText[2].IText = (UBYTE *)"Xmodem Receive";
  131. FileText[3].IText = (UBYTE *)"Xmodem Send";
  132.  
  133. return( 0 );
  134. }
  135.  
  136. /*****************************************************/
  137. /*                BaudRate  Menu                     */
  138. /*****************************************************/
  139.  
  140. /* define maximum number of menu items */
  141. #define RSMAX 5
  142.  
  143. /*   declare storage space for menu items and
  144.  *   their associated IntuiText structures
  145.  */
  146. struct MenuItem RSItem[RSMAX];
  147. struct IntuiText RSText[RSMAX];
  148.  
  149. /*****************************************************************/
  150. /*    The following function initializes the structure arrays    */
  151. /*   needed to provide the BaudRate menu topic.                  */
  152. /*****************************************************************/
  153. InitRSItems()
  154. {
  155. short n;
  156.  
  157. /* initialize each menu item and IntuiText with loop */
  158. for( n=0; n<RSMAX; n++ )
  159.    {
  160.    RSItem[n].NextItem = &RSItem[n+1];
  161.    RSItem[n].LeftEdge = 0;
  162.    RSItem[n].TopEdge = 11 * n;
  163.    RSItem[n].Width = 85;
  164.    RSItem[n].Height = 11;
  165.    RSItem[n].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT;
  166.    RSItem[n].MutualExclude = (~(1 << n));
  167.    RSItem[n].ItemFill = (APTR)&RSText[n];
  168.    RSItem[n].SelectFill = NULL;
  169.    RSItem[n].Command = 0;
  170.    RSItem[n].SubItem = NULL;
  171.    RSItem[n].NextSelect = 0;
  172.  
  173.    RSText[n].FrontPen = 0;
  174.    RSText[n].BackPen = 1;
  175.    RSText[n].DrawMode = JAM2;     /* render in fore and background */
  176.    RSText[n].LeftEdge = 0;
  177.    RSText[n].TopEdge = 1;
  178.    RSText[n].ITextFont = NULL;
  179.    RSText[n].NextText = NULL;
  180.    }
  181. RSItem[RSMAX-1].NextItem = NULL;
  182. /* 300 baud item chekced */
  183. RSItem[0].Flags = ITEMTEXT | ITEMENABLED | HIGHBOX | CHECKIT | CHECKED;
  184.  
  185. /* initialize text for specific menu items */
  186. RSText[0].IText = (UBYTE *)"   300";
  187. RSText[1].IText = (UBYTE *)"   1200";
  188. RSText[2].IText = (UBYTE *)"   2400";
  189. RSText[3].IText = (UBYTE *)"   4800";
  190. RSText[4].IText = (UBYTE *)"   9600";
  191.  
  192. return( 0 );
  193. }
  194.  
  195.  
  196. /***************************************************/
  197. /*                Menu Definition                  */
  198. /*                                                 */
  199. /*      This section of code is where the simple   */
  200. /*   menu definition goes.                         */
  201. /***************************************************/
  202.  
  203. /* current number of available menu topics */
  204. #define MAXMENU 2
  205.  
  206. /*   declaration of menu structure array for
  207.  *   number of current topics.  Intuition
  208.  *   will use the address of this array to
  209.  *   set and clear the menus associated with
  210.  *   the window.
  211.  */
  212. struct Menu menu[MAXMENU];
  213.  
  214. /**********************************************************************/
  215. /*   The following function initializes the Menu structure array with */
  216. /*  appropriate values for our simple menu strip.  Review the manual  */
  217. /*  if you need to know what each value means.                        */
  218. /**********************************************************************/
  219. InitMenu()
  220. {
  221. menu[0].NextMenu = &menu[1];
  222. menu[0].LeftEdge = 5;
  223. menu[0].TopEdge = 0;
  224. menu[0].Width = 50;
  225. menu[0].Height = 10;
  226. menu[0].Flags = MENUENABLED;
  227. menu[0].MenuName = "File";           /* text for menu-bar display */
  228. menu[0].FirstItem = &FileItem[0];    /* pointer to first item in list */
  229.  
  230. menu[1].NextMenu = NULL;
  231. menu[1].LeftEdge = 65;
  232. menu[1].TopEdge = 0;
  233. menu[1].Width = 85;
  234. menu[1].Height = 10;
  235. menu[1].Flags = MENUENABLED;
  236. menu[1].MenuName = "BaudRate";        /* text for menu-bar display */
  237. menu[1].FirstItem = &RSItem[0];    /* pointer to first item in list */
  238.  
  239. return( 0 );
  240. }
  241.  
  242. /* declarations for the serial stuff */
  243. extern struct MsgPort *CreatePort();
  244. struct IOExtSer *Read_Request;
  245. static char rs_in[2];
  246. struct IOExtSer *Write_Request;
  247. static char rs_out[2];
  248.  
  249. /******************************************************/
  250. /*                   Main Program                     */
  251. /*                                                    */
  252. /*      This is the main body of the program.         */
  253. /******************************************************/
  254.  
  255. main()
  256. {
  257. ULONG class;
  258. USHORT code,menunum,itemnum;
  259. int KeepGoing,capture,send;
  260. char c,name[32];
  261. FILE *tranr = NULL;
  262. FILE *trans = NULL;
  263.  
  264. IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", INTUITION_REV);
  265. if( IntuitionBase == NULL )
  266.    {
  267.    puts("can't open intuition\n");
  268.    exit(TRUE);
  269.    }
  270.  
  271. GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",GRAPHICS_REV);
  272. if( GfxBase == NULL )
  273.    {
  274.    puts("can't open graphics library\n");
  275.    exit(TRUE);
  276.    }
  277.  
  278. if(( mywindow = (struct Window *)OpenWindow(&NewWindow) ) == NULL)
  279.    {
  280.    puts("cant open window\n");
  281.    exit(TRUE);
  282.    }
  283.  
  284. Read_Request = (struct IOExtSer *)AllocMem(sizeof(*Read_Request),MEMF_PUBLIC|MEMF_CLEAR);
  285. Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  286. Read_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Read_RS",0);
  287. if(OpenDevice(SERIALNAME,NULL,Read_Request,NULL))
  288.    {
  289.    puts("Cant open Read device\n");
  290.    CloseWindow( mywindow );
  291.    DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
  292.    FreeMem(Read_Request,sizeof(*Read_Request));
  293.    exit(TRUE);
  294.    }
  295. Read_Request->IOSer.io_Command = CMD_READ;
  296. Read_Request->IOSer.io_Length = 1;
  297. Read_Request->IOSer.io_Data = (APTR) &rs_in[0];
  298.  
  299. Write_Request = (struct IOExtSer *)AllocMem(sizeof(*Write_Request),MEMF_PUBLIC|MEMF_CLEAR);
  300. Write_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  301. Write_Request->IOSer.io_Message.mn_ReplyPort = CreatePort("Write_RS",0);
  302. if(OpenDevice(SERIALNAME,NULL,Write_Request,NULL))
  303.    {
  304.    puts("Cant open Write device\n");
  305.    CloseWindow( mywindow );
  306.    DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
  307.    FreeMem(Write_Request,sizeof(*Write_Request));
  308.    DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
  309.    FreeMem(Read_Request,sizeof(*Read_Request));
  310.    exit(TRUE);
  311.    }
  312. Write_Request->IOSer.io_Command = CMD_WRITE;
  313. Write_Request->IOSer.io_Length = 1;
  314. Write_Request->IOSer.io_Data = (APTR) &rs_out[0];
  315.  
  316. Read_Request->io_SerFlags = SERF_SHARED | SERF_XDISABLED;
  317. Read_Request->io_Baud = 300;
  318. Read_Request->io_ReadLen = 8;
  319. Read_Request->io_WriteLen = 8;
  320. Read_Request->io_CtlChar = 1L;
  321. Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
  322. DoIO(Read_Request);
  323. Read_Request->IOSer.io_Command = CMD_READ;
  324.  
  325. InitFileItems();
  326. InitRSItems();
  327. InitMenu();
  328. SetMenuStrip(mywindow,&menu[0]);
  329.  
  330. KeepGoing = TRUE;
  331. capture=FALSE;
  332. send=FALSE;
  333. SetAPen(mywindow->RPort,1);
  334. emit(12);
  335. BeginIO(Read_Request);
  336.  
  337. while( KeepGoing )
  338.      {
  339.      /* wait for window message or serial port message */
  340.      Wait((1 << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) | ( 1 << mywindow->UserPort->mp_SigBit));
  341.  
  342.      if (send)
  343.          {
  344.          if ((c=getc(trans)) != EOF)
  345.              {
  346.              sendchar(c);
  347.              }
  348.          else
  349.              {
  350.              fclose(trans);
  351.              emits("\nFile Sent\n");
  352.              send=FALSE;
  353.              }
  354.          }
  355.      if(CheckIO(Read_Request))
  356.         {
  357.         WaitIO(Read_Request);
  358.         c=rs_in[0] & 0x7f;
  359.         BeginIO(Read_Request);
  360.         emit(c);
  361.         if (capture)
  362.             if (c > 31 && c < 127 || c == 10)  /* trash them mangy ctl chars */
  363.                 putc(c , tranr);
  364.         }
  365.  
  366.      while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
  367.           {
  368.           class = NewMessage->Class;
  369.           code = NewMessage->Code;
  370.           ReplyMsg( NewMessage );
  371.           switch( class )
  372.                 {
  373.                 case CLOSEWINDOW:
  374.                    /*   User is ready to quit, so indicate
  375.                    *   that execution should terminate
  376.                    *   with next iteration of the loop.
  377.                    */
  378.                    KeepGoing = FALSE;
  379.                 break;
  380.  
  381.                 case RAWKEY:
  382.                 /*  User has touched the keyboard */
  383.                 switch( code )
  384.                       {
  385.                       case 95: /* help key */
  386.                          emits("ESC Aborts Xmodem Xfer\n");
  387.                          emits("AMIGA Term 1.0\n");
  388.                          emits("Copyright 1985 by Michael Mounier\n");
  389.                       break;
  390.                       default:   
  391.                          c = toasc(code); /* get in into ascii */
  392.                          if (c != 0)
  393.                              {
  394.                              rs_out[0] = c;
  395.                              DoIO(Write_Request);
  396.                              }
  397.                       break;
  398.                       }
  399.                 break;
  400.  
  401.                 case NEWSIZE:
  402.                    emit(12);
  403.                 break;
  404.  
  405.                 case MENUPICK:
  406.                    if ( code != MENUNULL )
  407.                        {
  408.                        menunum = MENUNUM( code );
  409.                        itemnum = ITEMNUM( code );
  410.                        switch( menunum )
  411.                              {
  412.                              case 0:
  413.                                 switch( itemnum )
  414.                                       {
  415.                                       case 0:
  416.                                          if (capture == TRUE)
  417.                                              {
  418.                                              capture=FALSE;
  419.                                              fclose(tranr);
  420.                                              emits("\nEnd File Capture\n");
  421.                                              }
  422.                                          else
  423.                                              {
  424.                                              emits("\nAscii Capture:");
  425.                                              filename(name);
  426.                                              if ((tranr=fopen(name,"w")) == 0)
  427.                                                  {
  428.                                                  capture=FALSE;
  429.                                                  emits("\nError Opening File\n");
  430.                                                  break;
  431.                                                  }
  432.                                              capture=TRUE;
  433.                                              }
  434.                                       break;
  435.                                       case 1:
  436.                                          if (send == TRUE)
  437.                                              { 
  438.                                              send=FALSE;
  439.                                              fclose(trans);
  440.                                              emits("\nFile Send Cancelled\n");
  441.                                              }
  442.                                          else
  443.                                              {
  444.                                              emits("\nAscii Send:");
  445.                                              filename(name);
  446.                                              if ((trans=fopen(name,"r")) == 0)
  447.                                                  {
  448.                                                  send=FALSE;
  449.                                                  emits("\nError Opening File\n");
  450.                                                  break;
  451.                                                  }
  452.                                              send=TRUE;
  453.                                              }
  454.                                       break;
  455.                                       case 2:
  456.                                          emits("\nXmodem Receive:");
  457.                                          filename(name);
  458.                                          if (XMODEM_Read_File(name))
  459.                                             {
  460.                                             emits("\nRecieved File\n");
  461.                                             emit(8);
  462.                                             }
  463.                                          else
  464.                                             {
  465.                                             close(fd);
  466.                                             emits("Xmodem Receive Failed\n");
  467.                                             emit(8);
  468.                                             }
  469.                                       break;
  470.                                       case 3:
  471.                                          emits("\nXmodem Send:");
  472.                                          filename(name);
  473.                                          if (XMODEM_Send_File(name))
  474.                                              {
  475.                                              emits("\nSent File\n");
  476.                                              emit(8);
  477.                                              }
  478.                                          else
  479.                                              {
  480.                                              close(fd);
  481.                                              emits("\nXmodem Send Failed\n");
  482.                                              emit(8);
  483.                                              }
  484.                                       break;
  485.                                       }
  486.                              break;
  487.  
  488.                              case 1:
  489.                                 AbortIO(Read_Request);
  490.                                 switch( itemnum )
  491.                                       {
  492.                                       case 0:
  493.                                          Read_Request->io_Baud = 300;
  494.                                       break;
  495.                                       case 1:
  496.                                          Read_Request->io_Baud = 1200;
  497.                                       break;
  498.                                       case 2:
  499.                                          Read_Request->io_Baud = 2400;
  500.                                       break;
  501.                                       case 3:
  502.                                          Read_Request->io_Baud = 4800;
  503.                                       break;
  504.                                       case 4:
  505.                                          Read_Request->io_Baud = 9600;
  506.                                       break;
  507.                                       }
  508.                                 Read_Request->IOSer.io_Command = SDCMD_SETPARAMS;
  509.                                 DoIO(Read_Request);
  510.                                 Read_Request->IOSer.io_Command = CMD_READ;
  511.                                 BeginIO(Read_Request);
  512.                              break;
  513.                              } /* end of switch ( menunum ) */
  514.                        }    /*  end of if ( not null ) */
  515.                 }   /* end of switch (class) */
  516.           }   /* end of while ( newmessage )*/
  517.      }  /* end while ( keepgoing ) */
  518.  
  519. /*   It must be time to quit, so we have to clean
  520. *   up and exit.
  521. */
  522.        
  523. CloseDevice(Read_Request);
  524. DeletePort(Read_Request->IOSer.io_Message.mn_ReplyPort);
  525. FreeMem(Read_Request,sizeof(*Read_Request));
  526. CloseDevice(Write_Request);
  527. DeletePort(Write_Request->IOSer.io_Message.mn_ReplyPort);
  528. FreeMem(Write_Request,sizeof(*Write_Request));
  529. ClearMenuStrip( mywindow );
  530. CloseWindow( mywindow );
  531. exit(FALSE);
  532. } /* end of main */
  533.  
  534. /*************************************************
  535. *  function to get file name
  536. *************************************************/
  537. filename(name)
  538. char name[];
  539. {
  540. char c;
  541. ULONG class;
  542. USHORT code;
  543. int keepgoing,i;
  544. keepgoing = TRUE;
  545. i=0;
  546. while (keepgoing) {
  547.       while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) )
  548.            {
  549.            class = NewMessage->Class;
  550.            code = NewMessage->Code;
  551.            ReplyMsg( NewMessage );
  552.            if (class=RAWKEY)
  553.               {
  554.               c = toasc(code);
  555.               name[i]=c;
  556.               if (name[i] != 0)
  557.                  {
  558.                  if (name[i] == 13)
  559.                     {
  560.                     name[i]=0;
  561.                     keepgoing = FALSE;
  562.                     }
  563.                  else
  564.                     {
  565.                     if (name[i] == 8)
  566.                        {
  567.                        i -=2;
  568.                        if (i < -1)
  569.                           i = -1;
  570.                        else
  571.                           {
  572.                           emit(8);
  573.                           emit(32);
  574.                           emit(8);
  575.                           }
  576.                        }
  577.                     else
  578.                        emit(c);
  579.                     }
  580.                  i += 1;
  581.                  }
  582.               }
  583.           } /* end of new message loop */
  584.       }   /* end of god knows what */
  585.       emit(13);
  586. } /* end of function */
  587.  
  588.  
  589. /*************************************************
  590. *  function to print a string
  591. *************************************************/
  592. emits(string)
  593. char string[];
  594. {
  595. int i;
  596. char c;
  597.  
  598. i=0;
  599. while (string[i] != 0)
  600.       {
  601.       c=string[i];
  602.       if (c == 10)
  603.          c = 13;
  604.       emit(c);
  605.       i += 1;
  606.       }
  607. }
  608. /**************************************************************/
  609. /* send char and read char functions for the xmodem function */
  610. /************************************************************/
  611. sendchar(ch)
  612. int ch;
  613. {
  614. rs_out[0] = ch;
  615. DoIO(Write_Request);
  616. }
  617.  
  618. static unsigned char readchar()
  619. {
  620. unsigned char c;
  621. int rd,ch;
  622.  
  623. rd = FALSE;
  624.  
  625. while (rd == FALSE)
  626.       {
  627.       Wait((1 << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) | ( 1 << mywindow->UserPort->mp_SigBit));
  628.       if(CheckIO(Read_Request))
  629.         {
  630.         WaitIO(Read_Request);
  631.         ch=rs_in[0];
  632.         rd = TRUE;
  633.         BeginIO(Read_Request);
  634.         }
  635.       if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort))
  636.          if ((NewMessage->Class) == RAWKEY)
  637.             if ((NewMessage->Code) == 69)
  638.                {
  639.                emits("\nUser Cancelled Transfer");
  640.                break;
  641.                }
  642.       }
  643. if (rd == FALSE)
  644.    {
  645.    timeout = TRUE;
  646.    emits("\nTimeout Waiting For Character\n");
  647.    }
  648. c = ch;
  649. return(c);
  650. }
  651.  
  652. /**************************************/
  653. /* xmodem send and recieve functions */
  654. /************************************/
  655.  
  656. XMODEM_Read_File(file)
  657.     char *file;
  658. {
  659.     int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
  660.     unsigned int checksum, j, bufptr;
  661.     unsigned int i = 0;
  662.     char numb[10];
  663.     bytes_xferred = 0L;
  664.  
  665.     if ((fd = creat(file, 0)) < 0)
  666.         {
  667.         emits("Cannot Open File\n");
  668.         return FALSE;
  669.         }
  670.     else
  671.         emits("Receiving File\n");
  672.  
  673.     timeout=FALSE;
  674.     sectnum = errors = bufptr = 0;
  675.     sendchar(NAK);
  676.     firstchar = 0;
  677.     while (firstchar != EOT && errors != ERRORMAX)
  678.         {
  679.         errorflag = FALSE;
  680.  
  681.         do                                    /* get sync char */
  682.            {
  683.            firstchar = readchar();
  684.            if (timeout == TRUE)
  685.               return FALSE;
  686.            }
  687.         while (firstchar != SOH && firstchar != EOT);
  688.  
  689.         if  (firstchar == SOH)
  690.             {
  691.             emits("Getting Block ");
  692.             stci_d(numb,sectnum,i);
  693.             emits(numb);
  694.             emits("...");
  695.             sectcurr = readchar();
  696.             if (timeout == TRUE)
  697.                return FALSE;
  698.             sectcomp = readchar();
  699.             if (timeout == TRUE)
  700.                return FALSE;
  701.             if ((sectcurr + sectcomp) == 255)
  702.                 {
  703.                 if (sectcurr == (sectnum + 1 & 0xff))
  704.                     {
  705.                     checksum = 0;
  706.                     for (j = bufptr; j < (bufptr + SECSIZ); j++)
  707.                         {
  708.                         bufr[j] = readchar();
  709.                         if (timeout == TRUE)
  710.                            return FALSE;
  711.                         checksum = (checksum + bufr[j]) & 0xff;
  712.                         }
  713.                     if (checksum == readchar())
  714.                         {
  715.                         errors = 0;
  716.                         sectnum++;
  717.                         bufptr += SECSIZ;
  718.                         bytes_xferred += SECSIZ;
  719.                         emits("verified\n");
  720.                         if (bufptr == BufSize)
  721.                             {
  722.                             bufptr = 0;
  723.                             if (write(fd, bufr, BufSize) == EOF)
  724.                                 {
  725.                                 emits("\nError Writing File\n");
  726.                                 return FALSE;
  727.                                 };
  728.                             };
  729.                         sendchar(ACK);
  730.                         }
  731.                     else
  732.                         {
  733.                         errorflag = TRUE;
  734.                         if (timeout == TRUE)
  735.                            return FALSE;
  736.                         }
  737.                     }
  738.                 else
  739.                     {
  740.                     if (sectcurr == (sectnum & 0xff))
  741.                         {
  742.                         emits("\nReceived Duplicate Sector\n");
  743.                         sendchar(ACK);
  744.                         }
  745.                     else
  746.                         errorflag = TRUE;
  747.                     }
  748.                 }
  749.             else
  750.                 errorflag = TRUE;
  751.             }
  752.         if (errorflag == TRUE)
  753.             {
  754.             errors++;
  755.             emits("\nError\n");
  756.             sendchar(NAK);
  757.             }
  758.         };        /* end while */
  759.             
  760.     if ((firstchar == EOT) && (errors < ERRORMAX))
  761.         {
  762.         sendchar(ACK);
  763.         write(fd, bufr, bufptr);
  764.         close(fd);
  765.         return TRUE;
  766.         }
  767.     return FALSE;
  768. }
  769.  
  770. XMODEM_Send_File(file)
  771.     char *file;
  772. {
  773.     int sectnum, bytes_to_send, size, attempts, c;
  774.     int i = 0;
  775.     unsigned checksum, j, bufptr;
  776.     char numb[10];
  777.  
  778.     timeout=FALSE;
  779.     bytes_xferred = 0;
  780.     if ((fd = open(file, 1)) < 0)
  781.         {
  782.         emits("Cannot Open Send File\n");
  783.         return FALSE;
  784.         }
  785.     else
  786.         emits("Sending File\n");
  787.     attempts = 0;
  788.     sectnum = 1;
  789. /* wait for sync char */
  790.     j=1;
  791.     while (((c = readchar()) != NAK) && (j++ < ERRORMAX));
  792.     if (j >= (ERRORMAX))
  793.         {
  794.         emits("\nReceiver not sending NAKs\n");
  795.         return FALSE;
  796.         };
  797.  
  798.     while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX)
  799.         {
  800.         if (bytes_to_send == EOF)
  801.             {
  802.             emits("\nError Reading File\n");
  803.             return FALSE;
  804.             };
  805.  
  806.         bufptr = 0;
  807.         while (bytes_to_send > 0 && attempts != RETRYMAX)
  808.             {
  809.             attempts = 0;
  810.             do
  811.                 {
  812.                 sendchar(SOH);
  813.                 sendchar(sectnum);
  814.                 sendchar(~sectnum);
  815.                 checksum = 0;
  816.                 size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
  817.                 bytes_to_send -= size;
  818.                 for (j = bufptr; j < (bufptr + SECSIZ); j++)
  819.                     if (j < (bufptr + size))
  820.                         {
  821.                         sendchar(bufr[j]);
  822.                         checksum += bufr[j];
  823.                         }
  824.                     else
  825.                         {
  826.                         sendchar(0);
  827.                         }
  828.                 sendchar(checksum & 0xff);
  829.                 attempts++;
  830.                 c = readchar();
  831.                 if (timeout == TRUE)
  832.                    return FALSE;
  833.                 }
  834.             while ((c != ACK) && (attempts != RETRYMAX));
  835.             bufptr += size;
  836.             bytes_xferred += size;
  837.             emits("Block ");
  838.             stci_d(numb,sectnum,i);
  839.             emits(numb);
  840.             emits(" sent\n");
  841.             sectnum++;
  842.             }
  843.         }
  844.     close(fd);
  845.     if (attempts == RETRYMAX)
  846.         {
  847.         emits("\nNo Acknowledgment Of Sector, Aborting\n");
  848.         return FALSE;
  849.         }
  850.     else
  851.         {
  852.         attempts = 0;
  853.         do
  854.             {
  855.             sendchar(EOT);
  856.             attempts++;
  857.             }
  858.         while ((readchar() != ACK) && (attempts != RETRYMAX) && (timeout == FALSE));
  859.          if (attempts == RETRYMAX)
  860.             emits("\nNo Acknowledgment Of End Of File\n");
  861.         };
  862.     return TRUE;
  863. }
  864.  
  865. /*************************************************
  866. *  function to output ascii chars to window
  867. *************************************************/
  868. emit(c)
  869. char c;
  870. {
  871. static short x = 3;
  872. static short y = 17;
  873. short xmax,ymax,cx,cy;
  874.  
  875. xmax = mywindow->Width;
  876. ymax = mywindow->Height;
  877.  
  878. /* cursor */
  879. if (x > (xmax-31))
  880.    {
  881.    cx = 9;
  882.    cy = y + 8;
  883.    }
  884. else
  885.   {
  886.   cx = x+8;
  887.   cy = y;
  888.   }
  889.  
  890. if (cy > (ymax-2))
  891.    {
  892.    cx = 9;
  893.    cy -= 8;
  894.    }
  895.  
  896. SetDrMd(mywindow->RPort,COMPLEMENT);
  897. SetAPen(mywindow->RPort,3);
  898. RectFill(mywindow->RPort,cx-7,cy-6,cx,cy+1);
  899. SetAPen(mywindow->RPort,1);
  900. SetDrMd(mywindow->RPort,JAM2);
  901.  
  902. if (x > (xmax-31))
  903.    {
  904.    x = 3;
  905.    y += 8;
  906.    }
  907.  
  908. if (y > (ymax-2))
  909.    {
  910.    x = 3;
  911.    y -= 8;
  912.    }
  913.  
  914. Move(mywindow->RPort,x,y);
  915.  
  916. switch( c )
  917.       {
  918.       case '\t':
  919.          x += 60;
  920.          break;
  921.       case '\n':
  922.          break;
  923.       case 13:  /* newline */
  924.          x = 3;
  925.          y += 8;
  926.          break;
  927.       case 8:   /* backspace */
  928.          x -= 8;
  929.          if (x < 3)
  930.             x = 3;
  931.          break;
  932.       case 12:     /* page */
  933.          x = 3;
  934.          y = 17;
  935.          SetAPen(mywindow->RPort,0);
  936.          RectFill(mywindow->RPort,2,10,xmax-19,ymax-7);
  937.          SetAPen(mywindow->RPort,1);
  938.          break;
  939.       case 7:     /* bell */
  940.          ClipBlit(mywindow->RPort,0,0,mywindow->RPort,0,0,xmax,ymax,0x50);
  941.          ClipBlit(mywindow->RPort,0,0,mywindow->RPort,0,0,xmax,ymax,0x50);
  942.          break;
  943.       default:
  944.          Text(mywindow->RPort,&c,1);
  945.          x += 8;
  946.       } /* end of switch */
  947. /* cursor */
  948. if (x > (xmax-31))
  949.    {
  950.    cx = 9;
  951.    cy = y + 8;
  952.    }
  953. else
  954.   {
  955.   cx = x+8;
  956.   cy = y;
  957.   }
  958.  
  959. if (cy > (ymax-2))
  960.    {
  961.    cx = 9;
  962.    cy -= 8;
  963.    ScrollRaster(mywindow->RPort,0,8,2,10,xmax-20,ymax-2);
  964.    }
  965.  
  966. SetAPen(mywindow->RPort,3);
  967. RectFill(mywindow->RPort,cx-7,cy-6,cx,cy+1);
  968. SetAPen(mywindow->RPort,1);
  969. }
  970. /*************************************************
  971. *  function to take raw key data and convert it 
  972. *  into ascii chars
  973. **************************************************/
  974. static char toasc(code)
  975. USHORT code;
  976. {
  977. static int ctrl = FALSE;
  978. static int shift = FALSE;
  979. static int capsl = FALSE;
  980. char c;
  981. static char keys[75] = {
  982. '`' , '1' , '2' , '3' , '4' , '5' , '6' , '7' , '8' , '9' , '0' , '-' ,
  983. '=' , '\\' , 0 , '0' , 'q' , 'w' , 'e' , 'r' , 't' , 'y' , 'u' , 'i' , 'o' ,
  984. 'p' , '[' , ']' , 0 , '1' , '2' , '3' , 'a' , 's' , 'd' , 'f' , 'g' , 'h' ,
  985. 'j' , 'k' , 'l' , ';' , '\'' , 0 , 0 , '4' , '5' , '6' , 0 , 'z' , 'x' , 'c' , 'v' ,
  986. 'b' , 'n' , 'm' , 44 , '.' , '/' , 0 , '.' , '7' , '8' , '9' , ' ' , 8 ,
  987. '\t' , 13 , 13 , 27 , 127 , 0 , 0 , 0 , '-' } ;
  988.  
  989.              switch ( code ) /* I didn't know about the Quilifier field when I write this */
  990.                     {
  991.                     case 98:
  992.                        capsl = TRUE;
  993.                        c = 0;
  994.                        break;
  995.                     case 226:
  996.                        capsl = FALSE;
  997.                        c = 0;
  998.                        break;
  999.                     case 99:
  1000.                        ctrl = TRUE;
  1001.                        c = 0;
  1002.                        break;
  1003.                     case 227:
  1004.                        ctrl = FALSE;
  1005.                        c = 0;
  1006.                        break;
  1007.                     case 96:
  1008.                     case 97:
  1009.                        shift = TRUE;
  1010.                        c = 0;
  1011.                        break;
  1012.                     case 224:
  1013.                     case 225:
  1014.                        shift = FALSE;
  1015.                        c = 0;
  1016.                        break;
  1017.                    default:
  1018.                        if (code < 75)
  1019.                           c = keys[code];
  1020.                        else
  1021.                           c = 0;
  1022.                        }
  1023.          
  1024. /* add modifiers to the keys */
  1025.  
  1026. if (c != 0)
  1027.    {
  1028.  
  1029.    if (ctrl && (c <= 'z') && (c >= 'a'))
  1030.       c -= 96;
  1031.    else if (shift)
  1032.            {
  1033.       if ((c <= 'z') && (c >= 'a'))
  1034.          c -= 32;
  1035.       else
  1036.          switch( c )
  1037.                {
  1038.           case '[':
  1039.              c = '{';
  1040.              break;
  1041.           case ']':
  1042.              c = '}';
  1043.              break;
  1044.           case '\\':
  1045.              c = '|';
  1046.              break;
  1047.           case '\'':
  1048.              c = '"';
  1049.              break;
  1050.           case ';':
  1051.              c = ':';
  1052.              break;
  1053.           case '/':
  1054.              c = '?';
  1055.              break;
  1056.           case '.':
  1057.              c = '>';
  1058.              break;
  1059.           case ',':
  1060.              c = '<';
  1061.              break;
  1062.           case '`':
  1063.              c = '~';
  1064.              break;
  1065.           case '=':
  1066.              c = '+';
  1067.              break;
  1068.           case '-':
  1069.              c = '_';
  1070.              break;
  1071.           case '1':
  1072.              c = '!';
  1073.              break;
  1074.           case '2':
  1075.              c = '@';
  1076.              break;
  1077.           case '3':
  1078.              c = '#';
  1079.              break;
  1080.           case '4':
  1081.              c = '$';
  1082.              break;
  1083.           case '5':
  1084.              c = '%';
  1085.              break;
  1086.           case '6':
  1087.              c = '^';
  1088.              break;
  1089.           case '7':
  1090.              c = '&';
  1091.              break;
  1092.           case '8':
  1093.              c = '*';
  1094.              break;
  1095.           case '9':
  1096.              c = '(';
  1097.              break;
  1098.           case '0':
  1099.              c = ')';
  1100.              break;
  1101.           default:
  1102.           } /* end switch */
  1103.       } /* end shift */
  1104.    else if (capsl && (c <= 'z') && (c >= 'a'))
  1105.            c -= 32;
  1106.    } /* end modifiers */
  1107.    return(c);
  1108. } /* end of routine */
  1109. /* end of file */
  1110.  
  1111.  
  1112.  
  1113.